package cn.harry.modular.oss.service.impl;

import cn.harry.common.manager.AsyncManager;
import cn.harry.component.security.utils.SecurityUtils;
import cn.harry.modular.oss.factory.OssAsyncFactory;
import cn.harry.modular.oss.service.OssService;
import cn.harry.modular.system.domain.SysFile;
import cn.harry.modular.system.enums.BucketTypeEnums;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.IdUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import jakarta.annotation.PostConstruct;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.time.LocalDateTime;

/**
 * @author harry
 * @公众号 Harry技术
 */
@Component
@ConditionalOnProperty(value = "oss.type", havingValue = "aliyun")
@ConfigurationProperties(prefix = "oss.aliyun")
@RequiredArgsConstructor
@Data
public class AliyunOssServiceImpl implements OssService {
    /**
     * 服务Endpoint
     */
    private String endpoint;
    /**
     * 访问凭据
     */
    private String accessKeyId;
    /**
     * 凭据密钥
     */
    private String accessKeySecret;
    /**
     * 存储桶名称
     */
    private String bucketName;

    private OSS ossClient;

    @PostConstruct
    public void init() {
        ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
    }

    @Override
    @SneakyThrows
    public String uploadFile(MultipartFile file) {
        // 原文件名
        String originalFilename = file.getOriginalFilename();
        String type = file.getContentType();
        Long fileSize = file.getSize();
        // 文件后缀
        String suffix = FileUtil.getSuffix(originalFilename);
        String uuid = IdUtil.simpleUUID();
        // 新文件名
        String fileName = DateUtil.format(LocalDateTime.now(), "yyyyMMdd") + "/" + uuid + "." + suffix;
        //  try-with-resource 语法糖自动释放流
        try (InputStream inputStream = file.getInputStream()) {

            // 设置上传文件的元信息，例如Content-Type
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentType(file.getContentType());
            // 创建PutObjectRequest对象，指定Bucket名称、对象名称和输入流
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileName, inputStream, metadata);
            // 上传文件
            ossClient.putObject(putObjectRequest);
        } catch (Exception e) {
            throw new RuntimeException("文件上传失败");
        }
        String domain = "https://" + bucketName + "." + endpoint + "/" + fileName;

        SysFile sysFile = new SysFile(BucketTypeEnums.ALIYUN.name(), fileName, originalFilename, bucketName, type, fileSize, domain);
        // 保存数据库
        AsyncManager.me().execute(OssAsyncFactory.saveFileTask(sysFile, SecurityUtils.getSysUserIsNull()));
        return domain;
    }

    @Override
    public boolean deleteFile(String filePath) {
        Assert.notBlank(filePath, "删除文件路径不能为空");
        // 文件主机域名
        String fileHost = "https://" + bucketName + "." + endpoint;
        // +1 是/占一个字符，截断左闭右开
        String fileName = filePath.substring(fileHost.length() + 1);
        ossClient.deleteObject(bucketName, fileName);
        return true;
    }

}
